package edu.zju.gis.dbfg.queryserver.tool;

import edu.zju.gis.dbfg.queryserver.model.SearchResult;
import edu.zju.gis.dbfg.queryserver.model.vo.FeatureRecord;
import edu.zju.gis.dbfg.queryserver.model.vo.FeatureRecordsWithScroll;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static edu.zju.gis.dbfg.queryserver.constant.LimitedFieldsName.*;

public class FormatUtil {

    public static SearchResult SearchResponse2Result(SearchResponse response) {
        if (response != null) {
            SearchResult result = new SearchResult();
            result.setCurresult(response.getHits().getHits().length);
            result.setTotal(response.getHits().getTotalHits().value);
            result.setTime(response.getTook().getSecondsFrac());
            SearchHits hits = response.getHits();
            String id = response.getScrollId() != null ? response.getScrollId() : NO_SCROLL;
            result.setScrollId(id);
            List<Map<String, Object>> features = new ArrayList<>();
            for (SearchHit hit : hits) {
                Map<String, Object> item = hit.getSourceAsMap();
                item.put(DOC_ID_NAME, hit.getId());
                features.add(item);
            }
            result.setFeatures(features);
            return result;
        } else {
            System.out.println("THE CLIENT ERROR.");
            return null;
        }
    }

    public static FeatureRecord SearchResult2Record(SearchResult result, boolean needsGeom) {
        if (result == null) {
            System.out.println("Es 初始化失败。");
            return null;
        }
        FeatureRecord obj = new FeatureRecord();
        if (result.getFeatures().size() > 0) {
            Map<String, Object> firstMatch = result.getFeatures().get(0);
            if (needsGeom & firstMatch.keySet().contains(SPATIAL_FIELD_NAME)) {
                obj.setGeom(Shape2GeoJson(firstMatch.get(SPATIAL_FIELD_NAME)));
            }
            firstMatch.remove(SPATIAL_FIELD_NAME);
            obj.setAtt(firstMatch);
        }
        return obj;
    }

    public static List<FeatureRecord> SearchResult2Records(SearchResult result, boolean needsGeom) {
        if (result == null) {
            System.out.println("Es 初始化失败。");
            return null;
        }
        List<FeatureRecord> array = new ArrayList<>();
        for (Map<String, Object> temp : result.getFeatures()) {
            FeatureRecord obj = new FeatureRecord();
            if (needsGeom & temp.keySet().contains(SPATIAL_FIELD_NAME)) {
                obj.setGeom(Shape2GeoJson(temp.get(SPATIAL_FIELD_NAME)));
            }
            temp.remove(SPATIAL_FIELD_NAME);
            obj.setAtt(temp);
            array.add(obj);
        }
        return array;
    }

    public static FeatureRecordsWithScroll SearchResult2RecordsWithScroll(SearchResult result, boolean needsGeom) {
        if (result == null) {
            System.out.println("Es 初始化失败。");
            return null;
        }
        List<FeatureRecord> array = SearchResult2Records(result, needsGeom);
        FeatureRecordsWithScroll obj = new FeatureRecordsWithScroll();
        obj.setLastScroll(result.getScrollId());
        obj.setRecords(array);
        return obj;
    }

    public static String SearchResult2GeoJSON(SearchResult result) {
        if (result == null) {
            System.out.println("Es 初始化失败。");
            return null;
        }
        Map<String, Object> item = result.getFeatures().get(0);
        if (item.keySet().contains(SPATIAL_FIELD_NAME)) {
            Object obj = item.get(SPATIAL_FIELD_NAME);
            return Shape2GeoJson(obj);
        } else {
            System.out.println("空间字段读取失败。");
            return "";
        }
    }

    public static String Shape2GeoJson(Object shapeFromES) {
        JSONObject FeatureCollection = new JSONObject();
        JSONArray features = new JSONArray();
        JSONObject feature = new JSONObject();
        JSONObject geom = new JSONObject();
        Map<String, Object> source = (Map) shapeFromES;
        geom.put("coordinates", new JSONArray(source.get("coordinates").toString()));
        geom.put("type", source.get("type"));
        feature.put("type", "Feature");
        feature.put("properties", new JSONObject());
        feature.put("geometry", geom);
        features.put(feature);
        FeatureCollection.put("type", "FeatureCollection");
        FeatureCollection.put("features", features);
        return FeatureCollection.toString();
    }
}
